#ifndef INCLUDE_VECTORS_CSCALAR_H_
#define INCLUDE_VECTORS_CSCALAR_H_

/* Объект типа скаляр, с достоверностью */
template <typename T>
class CScalar
{
public:

	/**
	 * Инициализация скаляра, в результате которой получается вектор
	 * с произвольным значением (контструктором по умолчанию) и без достоверности
	 */
	CScalar() : value_(), valid_(false) {}

	/**
	 * Инициализация скаляра, с выбранными значениями
	 */
	CScalar(const T &value, const bool &valid) : value_(value), valid_(valid) {}

	/**
	 * Инициализация скаляра, через скаляр
	 */
	CScalar(const CScalar<T> &scalar) : value_(scalar.value_), valid_(scalar.valid_) {}

	virtual ~CScalar() {}

	/************************* Блок арифметических операций **************************/

	/**
	 * Приравнивание скаляров
	 */
	const CScalar<T> &operator= (const CScalar<T> &scalar)
	{
		value_ = scalar.value_;
		valid_ = scalar.valid_;

		return *this;
	}

	/**
	 * Приравнивание значения к скаляру
	 * Считается, что любое значение достоверно
	 */
	const CScalar<T> &operator= (const T &value)
	{
		value_ = value;
		valid_ = true;

		return *this;
	}

	/**
	 * Сложение скаляров
	 * Значения складываются.
	 * Сумма будет достоверной, только
	 * при наличии достоверных слагаемых
	 */
	const CScalar<T> operator+ (const CScalar<T> &scalar) const
	{
		return CScalar<T>(value_ + scalar.value_, valid_ && scalar.valid_);
	}

	/**
	 * Разница скаляров
	 * Значения вычитаются.
	 * Разница будет достоверной, только
	 * при наличии достоверных слагаемых
	 */
	const CScalar<T> operator- (const CScalar<T> &scalar) const
	{
		return CScalar<T>(value_ - scalar.value_, valid_ && scalar.valid_);
	}

	/**
	 * Сложение скаляров
	 * Значения складываются.
	 * Сумма будет достоверной, только
	 * при наличии достоверных слагаемых
	 */
	const CScalar<T> &operator+= (const CScalar<T> &scalar)
	{
		*this = *this + scalar;
		return *this;
	}

	/**
	 * Разница скаляров
	 * Значения вычитаются.
	 * Разница будет достоверной, только
	 * при наличии достоверных слагаемых
	 */
	const CScalar<T> &operator-= (const CScalar<T> &scalar)
	{
		return CScalar<T>(value_ - scalar.value_, valid_ && scalar.valid_);
	}

	/************************* Блок логических операций **************************
	 *
	 * Массив скаляров будет считаться отсортированным по убыванию, если:
	 * 1. Вначале идут большие валидные значения
	 * 2. Затем следуют малые валидные значения
	 * 3. Затем следуют большие невалидные значения
	 * 4. В конце идут малые невалидные значения
	 * Итого, как пример: (Значение, валидность)
	 * (10, 1), (5, 0), (3, 1), (15, 0), (1, 0)
	 * будут отсортированны, как
	 * (10, 1), (3, 1), (15, 0), (5, 0), (1, 0)
	 */

	/**
	 * Операция больше.
	 * Значение считается больше:
	 * Если при равных валидностях, оно больше
	 * Или оно валидно, при прочих условиях
	 */
	bool operator> (const CScalar<T> &scalar)
	{
		return valid_ == scalar.valid_ ?
				value_ > scalar.value_ :
				valid_;
	}

	/**
	 * Операция меньше.
	 * Значение считается меньше:
	 * Если при равных валидностях, оно меньше
	 * Или оно невалидно, при прочих условиях
	 */
	bool operator< (const CScalar<T> &scalar)
	{
		return valid_ == scalar.valid_ ?
				value_ < scalar.value_ :
				!valid_;
	}

	/**
	 * Операция равны.
	 * Значения считается равными:
	 * Если значения и валидности соответствуют друг другу
	 */
	bool operator== (const CScalar<T> &scalar)
	{
		return valid_ == scalar.valid_ &&
				value_ == scalar.value_;
	}

	/**
	 * Операция неравны.
	 * Значения считается неравными:
	 * Если значения или валидности несоответствуют друг другу
	 */
	bool operator!= (const CScalar<T> &scalar)
	{
		return valid_ != scalar.valid_ ||
				value_ != scalar.value_;
	}

	/**
	 * Операция больше или равны.
	 */
	bool operator>= (const CScalar<T> &scalar)
	{
		return *this > scalar ||
				*this == scalar;
	}

	/**
	 * Операция меньше или равны.
	 */
	bool operator<= (const CScalar<T> &scalar)
	{
		return *this < scalar ||
				*this == scalar;
	}

	/**
	 * Получить значение скаляра
	 */
	inline const T &getValue() const { return value_; }
	/**
	 * Получить достоверность скаляра
	 */
    inline const bool &getValid() const { return valid_; }

	/**
	 * Получить значение скаляра
	 */
	inline void setValue(T value) { value_ = value; }
	/**
	 * Получить достоверность скаляра
	 */
	inline void setValid(bool valid) { valid_ = valid; }

	/* Невалидный скаляр, который получается по-умолчанию */
	static const CScalar<T> zero;

protected:
	/* Значение */
	T value_;
	/* Достоверность */
	bool valid_;
};

#endif /* INCLUDE_VECTORS_CSCALAR_H_ */
